package com.tarena.lbs.marketing.web.service;

import com.github.pagehelper.PageInfo;
import com.tarena.lbs.base.common.utils.Asserts;
import com.tarena.lbs.base.protocol.exception.BusinessException;
import com.tarena.lbs.base.protocol.pager.PageResult;
import com.tarena.lbs.basic.api.AdminApi;
import com.tarena.lbs.common.passport.enums.Roles;
import com.tarena.lbs.common.passport.principle.UserPrinciple;
import com.tarena.lbs.common.security.utils.LbsSecurityContenxt;
import com.tarena.lbs.marketing.web.repository.CouponCodeRepository;
import com.tarena.lbs.marketing.web.repository.CouponRepository;
import com.tarena.lbs.pojo.basic.dto.AdminDTO;
import com.tarena.lbs.pojo.marketing.param.CouponParam;
import com.tarena.lbs.pojo.marketing.po.CouponCodePO;
import com.tarena.lbs.pojo.marketing.po.CouponPO;
import com.tarena.lbs.pojo.marketing.query.CouponQuery;
import com.tarena.lbs.pojo.marketing.vo.CouponVO;
import com.tarena.lbs.pojo.stock.param.CouponStockParam;
import com.tarena.lbs.stock.api.StockApi;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.dubbo.config.annotation.DubboReference;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

@Service
public class CouponService {
    @Autowired
    private CouponRepository couponRepository;
    @Autowired
    private CouponCodeRepository couponCodeRepository;
    @DubboReference
    private StockApi stockApi;
    public PageResult<CouponVO> couponPage(CouponQuery couponQuery) throws BusinessException {
        //1.取登录认证用户 验证
        UserPrinciple userPrinciple= LbsSecurityContenxt.getLoginToken();
        Asserts.isTrue(userPrinciple==null,new BusinessException("-2","用户认证失败"));
        Asserts.isTrue(userPrinciple.getRole()!= Roles.SHOP,new BusinessException("-2","角色权限不正确"));
        //2.获取登录用户的admin详情 需要的是businessId
        Integer businessId=getShopBusinessId(userPrinciple.getId());
        couponQuery.setBusinessId(businessId);
        //3.分装查询条件 仓储层要数据
        PageInfo<CouponPO> poPageInfo=couponRepository.getCouponsByPage(couponQuery);
        PageResult<CouponVO> voPages=new PageResult<>();
        voPages.setPageNo(poPageInfo.getPageNum());
        voPages.setPageSize(poPageInfo.getPageSize());
        voPages.setTotal(poPageInfo.getTotal());
        List<CouponVO> vos=null;
        if (poPageInfo.getTotal()>0){
            vos=poPageInfo.getList().stream().map(po->{
                CouponVO vo=new CouponVO();
                BeanUtils.copyProperties(po,vo);
                return vo;
            }).collect(Collectors.toList());
        }
        voPages.setObjects(vos);
        return voPages;
    }
    @DubboReference
    private AdminApi adminAPI;
    private Integer getShopBusinessId(Integer id) throws BusinessException {
        AdminDTO adminDetail = adminAPI.getAdminDetail(id);
        Asserts.isTrue(adminDetail==null||adminDetail.getId()==null,new BusinessException("-2","不存在该 商家"));
        Integer businessId = adminDetail.getBusinessId();
        return businessId;
    }
    @Transactional(rollbackFor = Exception.class)
    public void couponSave(CouponParam couponParam) throws BusinessException, ParseException {
        //1. 解析登录用户 验证合法
        UserPrinciple userPrinciple= LbsSecurityContenxt.getLoginToken();
        Asserts.isTrue(userPrinciple==null,new BusinessException("-2","用户认证失败"));
        Asserts.isTrue(userPrinciple.getRole()!= Roles.SHOP,new BusinessException("-2","角色权限不正确"));
        //2. 获取登录用户的admin详情 需要的是businessId
        Integer businessId = getShopBusinessId(userPrinciple.getId());
        //3.封装couponPO所需属性
        CouponPO couponPO=new CouponPO();
        BeanUtils.copyProperties(couponParam,couponPO);
        //入参没有传递的属性 businessId createAt updateAte status(0未领取 1已领取 2已消费) enableStatus(是否启用)
        //手动根据入参的起始和结束时间转化date
        couponPO.setBusinessId(businessId);
        couponPO.setCreateAt(new Date());
        couponPO.setUpdateAt(couponPO.getCreateAt());
        couponPO.setStatus(0);
        couponPO.setEnableStatus(0);
        couponPO.setStartDate(DateUtils.parseDate(couponParam.getStartDate(),"yyyy-MM-dd HH:mm:ss"));
        couponPO.setEndDate(DateUtils.parseDate(couponParam.getEndDate(),"yyyy-MM-dd HH:mm:ss"));
        couponRepository.saveCoupon(couponPO);//coupon insert
        //根据当前的优惠券Id生成一批优惠券码的数据
        List<CouponCodePO> couponCodes=initCouponCodes(couponPO);//比如优惠券发行量100张,每张都有一个唯一编码
        couponCodeRepository.saveBatch(couponCodes);
        //远程 调用初始化库存
        initCouponStock(couponPO);
    }

    private List<CouponCodePO> initCouponCodes(CouponPO couponPO) {
        //为每一张优惠券 初始他maxUsageLimit个数的 优惠券码.
        Integer total = couponPO.getMaxUsageLimit();
        //准备一个数组 集合
        List<CouponCodePO> poParams=new ArrayList<>();
        for (int i=0;i<total;i++){
            //构造一个couponCodepo 写入数组
            CouponCodePO poParam=new CouponCodePO();
            poParam.setBusinessId(couponPO.getBusinessId());
            poParam.setCouponId(couponPO.getId());
            poParam.setCouponCode(UUID.randomUUID().toString());
            poParam.setStatus(0);//0 未领取 1 已领取 2 已使用 3 已退还 4...
            poParam.setCreateAt(couponPO.getCreateAt());
            poParam.setUpdateAt(couponPO.getCreateAt());
            poParams.add(poParam);
        }
        return poParams;
    }

    private void initCouponStock(CouponPO couponPO) throws BusinessException {
        CouponStockParam param=new CouponStockParam();
        param.setCouponId(couponPO.getId());
        param.setBusinessId(couponPO.getBusinessId());
        param.setNum(couponPO.getMaxUsageLimit());
        boolean result = stockApi.initCouponStock(param);
        Asserts.isTrue(!result,new BusinessException("-2","初始化库存失败"));
    }

    public CouponVO couponDetail(Integer id) {
        CouponPO po = couponRepository.getCouponById(id);
        CouponVO vo=null;
        if (po!=null){
            vo=new CouponVO();
            BeanUtils.copyProperties(po,vo);
        }
        return vo;
    }
}
